<?php
/**
 * 事件
 * 
 * @author ShuangYa
 * @package APIGateway
 * @category Library
 * @link https://www.sylingd.com/
 * @copyright Copyright (c) 2018 ShuangYa
 * @license https://www.sylibs.com/go/apigateway/license
 */
namespace ag\library;

use yesf\Yesf;
use yesf\Constant;
use yesf\library\Plugin;
use yesf\library\Swoole;
use Swoole\Coroutine as co;

use ag\model\App;
use ag\model\Config;
use APIGateway\Protobuf\Response;

class Event {
	/**
	 * HTTP分发
	 * 
	 * @access public
	 * @param string $module
	 * @param string $controller
	 * @param string $action
	 * @param object $request
	 * @param object $response
	 */
	public static function onDispatcher($module, $controller, $action, $request, $response) {
		if ($request->server['request_method'] === 'OPTIONS') {
			$response->header('Access-Control-Allow-Origin', $request->header['origin']);
			$response->header('Access-Control-Allow-Credentials', 'true');
			return TRUE;
		}
		if ($module === 'admin' && $controller !== 'index') {
			$response->header('Content-Type', 'application/json; charset=UTF-8');
			//检查登录状态
			if (!isset($request->header['x-admin-password'])) {
				$response->write(Utils::getWebApiResult([
					'error' => '未登录'
				]));
				return FALSE;
			}
			$admin = $request->header['x-admin-password'];
			if ($admin !== Config::getInstance()->read('admin_password')) {
				$response->write(Utils::getWebApiResult([
					'error' => '未登录'
				]));
				return FALSE;
			}
		}
		return NULL;
	}
	/**
	 * Worker启动
	 * 
	 * @access public
	 * @param boolean $is_taskworker
	 * @param int $worker_id
	 */
	public static function onWorkerStart($is_taskworker, $worker_id) {
		if ($is_taskworker) {
			return;
		}
		//自动注册
		$list = require(SERVICE_PATH . 'list.php');
		foreach ($list as $v) {
			if (is_file(SERVICE_PATH . $v['name'] . '.php')) {
				$clazz = 'ag\\service\\' . $v['name'];
				if (class_exists($clazz) && is_subclass_of($clazz, ServiceInterface::class)) {
					Dispatcher::register($v['name'], $clazz, $v['id']);
				}
			}
		}
	}
	/**
	 * 注册TCP监听
	 * 
	 * @access public
	 */
	public static function registerTcpListen() {
		$tcp = Yesf::getProjectConfig('tcp');
		if (!$tcp) {
			return;
		}
		//注册TCP监听
		$config = [
			'ip' => $tcp['ip'],
			'port' => $tcp['port'],
			'advanced' => [
				'open_length_check' => 1,
				'package_length_type' => 'N',
				'package_length_offset' => 0,
				'package_body_offset' => 4,
				'package_max_length' => 2097152, // 1024 * 1024 * 2,
				'buffer_output_size' => 3145728, //1024 * 1024 * 3,
				'open_tcp_nodelay' => 1,
				'backlog' => 3000
			]
		];
		Swoole::addListener(Constant::LISTEN_TCP, $config, [__CLASS__, 'onTcpReceive']);
	}
	/**
	 * 处理类似于TCP的请求并返回结果
	 * 
	 * @access protected
	 * @param string $event
	 * @param int $fd
	 * @param int $from_id
	 * @param string $data
	 */
	public static function onTcpReceive($event, $fd, $from_id, $data) {
		if ($event !== 'receive') {
			return;
		}
		$data = substr($data, 4);
		//心跳包，不进行处理
		if ($data === 'heartbeat') {
			$sendStr = 'heartbeat';
			goto TCP_FINISH_SEND;
		}
		//进行转发
		try {
			$req = Dispatcher::parse($data);
		} catch (\Exception $e) {
			$sendStr = Dispatcher::createResult(Dispatcher::CODE_WRONG_REQUEST, "")->serializeToString();
		}
		if (!isset($sendStr)) {
			$sendStr = Dispatcher::dispatch($req)->serializeToString();
		}
TCP_FINISH_SEND:
		//发送
		$sendStr = pack('N', strlen($sendStr)) . $sendStr;
		Swoole::send($sendStr, $fd, $from_id);
	}
	/**
	 * TODO: 处理Task进程的请求
	 * 
	 * @access public
	 * @param int $task_id
	 * @param int $worker_id
	 * @param string $data
	 * @return string
	 */
	public static function onTask($task_id, $worker_id, $data) {
	}
}